home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-serious-
/
programming
/
c
/
simplecalc
/
calc.math.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-28
|
9KB
|
343 lines
/* -----------------------------------------------------------
$VER: calc.math.c 1.01 (22.02.2000)
maths core for calculator project
(C) Copyright 2000 Matthew J Fletcher - All Rights Reserved.
amimjf@connectfree.co.uk - www.amimjf.connectfree.co.uk
------------------------------------------------------------ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos/dos.h>
#include <exec/types.h>
#include <exec/exec.h>
#include <libraries/gadtools.h>
#include <graphics/gfxmacros.h>
#include <graphics/gfxbase.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include "Calc.h"
#define MAX 255 /* max char precision */
/* buffers for maths core preserved betwen calls */
long double result=0; /* final total */
char number1[MAX]; /* first number */
char op; /* math op */
char number2[MAX]; /* second number */
int i=0,y=0;
int flag=0,sflag=0; /* control flags */
/* tape history */
extern int UseTape;
/* maths mode */
extern int mode;
/* whats on screen */
extern char buffer[100];
double do_math(char inchar)
{ /* maths core for calculator */
char *t1,*t2;
static long double realnumber1,realnumber2,realresult;
/* if previous result exists & op is first gad pressed */
if ( ((inchar == '+' ) || (inchar == '-' ) || (inchar == '/' ) ||
(inchar == '*' )) && (result != 0)
)
/* second or more calc */
{
op = inchar; /* store */
// printf("operation (%c)\n",op);
draw_op(op);
flag =1; /* now only fill second number */
sflag =1; /* calc, uses stored number as number1 */
/* copy previous result to number1 store */
realnumber1 = result;
}
/* if input is number and op is blank store */
if ( ((isdigit(inchar) != 0) || (inchar =='.')) && (flag ==0))
/* make sure we are first number */
{
/* first distroy, old result, cos user did NOT, want */
/* to perform an operation on it (they started to type */
/* a new number !!) */
result=0;
number1[i] = inchar; /* add next input */
i++;
// printf("1stored (%c), number1 (%s)\n",inchar, number1);
clear_display();
draw_display(number1,NULL);
}
/* if input is number and op is NOT blank store */
if (((isdigit(inchar) != 0) || (inchar =='.')) && (flag ==1))
/* make sure we are second number */
{
number2[y] = inchar; /* add next input */
y++;
// printf("2stored (%c), number2 (%s)\n",inchar, number2);
clear_display();
draw_display(number2,NULL);
}
/* if we get a operations store */
if ( (inchar == '+' ) || (inchar == '-' ) || (inchar == '/' ) ||
(inchar == '*' ) || (inchar == '(' ) || (inchar == ')' ) ||
(inchar == '<' ) && (sflag == 0) /* skip if op allready parsed */
) /* its an operation */
{
op = inchar; /* store */
// printf("operation (%c)\n",op);
clear_display();
draw_op(op);
draw_display(NULL,NULL); /* a refresh basicly */
flag =1; /* now only fill second number */
}
/* if = pressed */
if (inchar == '=')
{
/* we work out result imedieatly */
/* convert to numbers */
if (sflag ==0) realnumber1 = strtod(number1, &t1);
/* or not if one is available */
if (sflag ==1) realnumber1 = result;
realnumber2 = strtod(number2, &t2);
/* second number always input */
if (UseTape ==1)
printf("%Lg %c %Lg\n ",realnumber1,op,realnumber2);
switch (op)
{
case '+':
realresult = (realnumber1 + realnumber2);
break;
case '-':
realresult = (realnumber1 - realnumber2);
break;
case '/':
realresult = (realnumber1 / realnumber2);
break;
case '*':
realresult = (realnumber1 * realnumber2);
break;
default:
printf("Something broke, couldent get operand ! got (%c)\n",op);
break;
};
/* copy to store */
result = realresult;
/* output conversion depends on mode selected */
/* ALL maths done internally as decimal */
switch (mode)
{
case 0: /* DEC */
/* copy data for display */
sprintf(buffer, "%Ld",realresult);
/* tape display */
if (UseTape ==1)
printf("=%s %Ld%s\n",BOLD,realresult,NORMAL);
break;
case 1: /* FLT */
sprintf(buffer, "%Lg",realresult);
if (UseTape ==1)
printf("=%s %Lg%s\n",BOLD,realresult,NORMAL);
break;
case 2: /* HEX */
sprintf(buffer, "%Lx",realresult);
if (UseTape ==1)
printf("=%s %Lx%s\n",BOLD,realresult,NORMAL);
break;
case 3: /* OCT */
sprintf(buffer, "%Lo",realresult);
if (UseTape ==1)
printf("=%s %Lo%s\n",BOLD,realresult,NORMAL);
break;
case 4: /* BIN */
sprintf(buffer, "%Ld",realresult);
/* display return from atob (int) */
if (UseTape ==1)
printf("=%s %Ld%s\n",BOLD,atob(buffer),NORMAL);
break;
case 5: /* EXPO */
sprintf(buffer, "%Le",realresult);
if (UseTape ==1)
printf("=%s %.Le%s\n",BOLD,realresult,NORMAL);
break;
};
/* check for overload */
if (stricmp(buffer,"NaN")==0)
strcpy(buffer,"Overload !!");
/* clean our mess */
clear_buffers();
clear_display();
draw_display(buffer,NULL);
/* we are safe to call again now */
} /* end calculation */
} /* end do_math */
int draw_display(char *inchar, int mode)
{ /* re-draw display */
static int smode;
/* store untill, user changes */
if (mode != NULL)
smode = mode;
/* NULL for no change */
/* print maths mode */
switch (smode)
{
case 0: /* DEC */
GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
GTTX_Text, (STRPTR)"DEC", TAG_END);
break;
case 1: /* FLT */
GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
GTTX_Text, (STRPTR)"FLT", TAG_END);
break;
case 2: /* HEX */
GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
GTTX_Text, (STRPTR)"HEX", TAG_END);
break;
case 3: /* OCT */
GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
GTTX_Text, (STRPTR)"OCT", TAG_END);
break;
case 4: /* BIN */
GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
GTTX_Text, (STRPTR)"BIN", TAG_END);
break;
case 5: /* EXPO */
GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
GTTX_Text, (STRPTR)"EXPO", TAG_END);
break;
};
/* print display */
if (inchar != NULL)
GT_SetGadgetAttrs(CalcGadgets[24], CalcWnd, NULL,
GTTX_Text, (STRPTR)inchar, TAG_END);
/* NULL passed, if no change required */
/* note we dont buffer the display buffer!! */
/* so it needs to be re-passed, if you want */
/* a display and/or an update */
} /* end draw_display */
void clear_display(void)
{
/* just draw a filed rectangle over display */
/* re-calc each time for font size change */
BYTE BorderLeft = CalcWnd->BorderLeft;
BYTE BorderTop = CalcWnd->BorderTop;
BYTE BorderRight = CalcWnd->BorderRight;
BYTE BorderBottom = CalcWnd->BorderBottom;
//SetAPen(CalcWnd->RPort,4); /* dark grey */
//RectFill(CalcWnd->RPort,11,13,210,27);
GT_SetGadgetAttrs(CalcGadgets[24], CalcWnd, NULL,
GTTX_Text, (STRPTR)" ", TAG_END);
GT_SetGadgetAttrs(CalcGadgets[25], CalcWnd, NULL,
GTTX_Text, (STRPTR)" ", TAG_END);
} /* end clear display */
void clear_buffers(void)
{
int x=0;
/* if erase selected or CA, we flush all internal */
/* data stores, so we can start again */
i=0,y=0;
flag=0; /* pointers */
sflag=0;
for (x=0; x != MAX; x++) /* stores */
{ number1[x] =0;
number2[x] =0;
}
/* we are safe to call again now */
} /* end clear buffers */
void draw_op(char op)
{ /* place operation on display */
switch (op)
{ /* print op type */
case '+':
GT_SetGadgetAttrs(CalcGadgets[26], CalcWnd, NULL,
GTTX_Text, (STRPTR)"+", TAG_END);
break;
case '-':
GT_SetGadgetAttrs(CalcGadgets[26], CalcWnd, NULL,
GTTX_Text, (STRPTR)"-", TAG_END);
break;
case '/':
GT_SetGadgetAttrs(CalcGadgets[26], CalcWnd, NULL,
GTTX_Text, (STRPTR)"/", TAG_END);
break;
case '*':
GT_SetGadgetAttrs(CalcGadgets[26], CalcWnd, NULL,
GTTX_Text, (STRPTR)"*", TAG_END);
break;
};
} /* end print op */
int atob(char *str)
/* ASCII-to-binary conversion */
{
int val;
for (val = 0; *str; str++)
{
val *= 2;
if (*str == '1')
val++;
else if (*str != '0')
return(-1);
}
return(val);
}